﻿using Microsoft.EntityFrameworkCore;
using Microsoft.OpenApi.Models;
using Serilog;
using Serilog.Events;
using Serilog.Extensions.Logging;
using MediPlatform.Infeartructure;
using MediPlatform.Read.Api.Services;
using System.Reflection;

namespace MediPlatform.Read.Api.Extensions
{
    /// <summary>
    /// 服务集合扩展类
    /// </summary>
    public static class ServiceCollectionExtensions
    {
        /// <summary>
        /// 添加数据库服务
        /// </summary>
        /// <param name="services">服务集合</param>
        /// <param name="configuration">配置</param>
        /// <returns>服务集合</returns>
        public static IServiceCollection AddDatabaseServices(this IServiceCollection services, IConfiguration configuration)
        {
            // 添加数据库上下文
            services.AddDbContext<MyDbContext>(options =>
            {
                var connectionString = configuration.GetConnectionString("SQL");
                
                // 直接使用MySQL提供程序
                var serverVersion = ServerVersion.AutoDetect(connectionString);
                options.UseMySql(connectionString, serverVersion, mySqlOptions =>
                {
                    // 配置MySQL特定选项
                    mySqlOptions.EnableRetryOnFailure(
                        maxRetryCount: 5,
                        maxRetryDelay: TimeSpan.FromSeconds(30),
                        errorNumbersToAdd: null);
                });
            });

            return services;
        }

        /// <summary>
        /// 添加仓储服务
        /// </summary>
        /// <param name="services">服务集合</param>
        /// <returns>服务集合</returns>
        public static IServiceCollection AddRepositoryServices(this IServiceCollection services)
        {
            // 注册基础仓储接口和实现
            services.AddScoped(typeof(IBaseRepository<>), typeof(BaseRepository<>));

            return services;
        }

        /// <summary>
        /// 添加日志服务
        /// </summary>
        /// <param name="services">服务集合</param>
        /// <param name="configuration">配置</param>
        /// <returns>服务集合</returns>
        public static IServiceCollection AddLoggingServices(this IServiceCollection services, IConfiguration configuration)
        {
            // 配置Serilog
            Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Information()
                .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
                .MinimumLevel.Override("System", LogEventLevel.Warning)
                .Enrich.FromLogContext()
                .WriteTo.Console()
                .WriteTo.File(
                    path: "logs/mediplatform-.log",
                    rollingInterval: RollingInterval.Day,
                    outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}",
                    retainedFileCountLimit: 30)
                .CreateLogger();

            services.AddLogging(loggingBuilder =>
            {
                loggingBuilder.AddSerilog(dispose: true);
            });

            return services;
        }

        /// <summary>
        /// 添加Swagger服务
        /// </summary>
        /// <param name="services">服务集合</param>
        /// <returns>服务集合</returns>
        public static IServiceCollection AddSwaggerServices(this IServiceCollection services)
        {
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo
                {
                    Title = "智慧医疗平台 API",
                    Version = "v1",
                    Description = "智慧医疗平台读取API接口文档",
                    Contact = new OpenApiContact
                    {
                        Name = "开发团队",
                        Email = "dev@mediplatform.com"
                    }
                });

                // 添加XML注释支持
                var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
                var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
                if (File.Exists(xmlPath))
                {
                    c.IncludeXmlComments(xmlPath);
                }

                // 添加JWT认证支持
                c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
                {
                    Description = "JWT授权(数据将在请求头中进行传输) 参数结构: \"Authorization: Bearer {token}\"",
                    Name = "Authorization",
                    In = ParameterLocation.Header,
                    Type = SecuritySchemeType.ApiKey,
                    BearerFormat = "JWT",
                    Scheme = "Bearer"
                });

                c.AddSecurityRequirement(new OpenApiSecurityRequirement
                {
                    {
                        new OpenApiSecurityScheme
                        {
                            Reference = new OpenApiReference
                            {
                                Type = ReferenceType.SecurityScheme,
                                Id = "Bearer"
                            }
                        },
                        new string[] {}
                    }
                });
            });

            return services;
        }

        /// <summary>
        /// 添加CORS服务
        /// </summary>
        /// <param name="services">服务集合</param>
        /// <returns>服务集合</returns>
        public static IServiceCollection AddCorsServices(this IServiceCollection services)
        {
            services.AddCors(options =>
            {
                options.AddPolicy("AllowAll", policy =>
                {
                    policy.AllowAnyOrigin()
                          .AllowAnyMethod()
                          .AllowAnyHeader();
                });

                options.AddPolicy("AllowSpecific", policy =>
                {
                    policy.WithOrigins("http://localhost:3000", "https://localhost:3000")
                          .AllowAnyMethod()
                          .AllowAnyHeader()
                          .AllowCredentials();
                });
            });

            return services;
        }

        /// <summary>
        /// 添加缓存服务
        /// </summary>
        /// <param name="services">服务集合</param>
        /// <returns>服务集合</returns>
        public static IServiceCollection AddCacheServices(this IServiceCollection services)
        {
            // 添加内存缓存
            services.AddMemoryCache();

            return services;
        }

        /// <summary>
        /// 添加AutoMapper服务
        /// </summary>
        /// <param name="services">服务集合</param>
        /// <returns>服务集合</returns>
        public static IServiceCollection AddAutoMapperServices(this IServiceCollection services)
        {
            // 注册AutoMapper
            services.AddAutoMapper(typeof(Program).Assembly);

            return services;
        }

        /// <summary>
        /// 添加JWT认证服务
        /// </summary>
        /// <param name="services">服务集合</param>
        /// <param name="configuration">配置</param>
        /// <returns>服务集合</returns>
        public static IServiceCollection AddJwtAuthenticationServices(this IServiceCollection services, IConfiguration configuration)
        {
            // 注册JWT服务
            services.AddScoped<JwtService>();
            services.AddScoped<AuthService>();
            services.AddScoped<DatabaseInitializer>();

            // 配置JWT认证
            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = "Bearer";
                options.DefaultChallengeScheme = "Bearer";
            })
            .AddJwtBearer("Bearer", options =>
            {
                options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
                {
                    ValidateIssuer = true,
                    ValidateAudience = true,
                    ValidateLifetime = true,
                    ValidateIssuerSigningKey = true,
                    ValidIssuer = configuration["Jwt:Issuer"] ?? "MediPlatform",
                    ValidAudience = configuration["Jwt:Audience"] ?? "MediPlatformUsers",
                    IssuerSigningKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(
                        System.Text.Encoding.ASCII.GetBytes(configuration["Jwt:SecretKey"] ?? "YourSuperSecretKey12345678901234567890"))
                };
            });

            return services;
        }

        /// <summary>
        /// 添加业务服务
        /// </summary>
        /// <param name="services">服务集合</param>
        /// <returns>服务集合</returns>
        public static IServiceCollection AddBusinessServices(this IServiceCollection services)
        {
            // 注册退款申请服务
            services.AddScoped<RefundApplicationService>();
            services.AddScoped<RefundApplicationDataInitializer>();

            // 注册药品订单服务
            services.AddScoped<MedicalOrderService>();
            services.AddScoped<MedicalOrderDataInitializer>();

            // 注册处方流转订单服务
            services.AddScoped<PrescriptionOrderService>();
            services.AddScoped<PrescriptionOrderDataInitializer>();

            // 注册问诊单服务
            services.AddScoped<ConsultationOrderService>();
            services.AddScoped<ConsultationOrderDataInitializer>();

            // 注册挂号订单服务
            services.AddScoped<RegistrationOrderService>();
            services.AddScoped<RegistrationOrderDataInitializer>();

            return services;
        }

        /// <summary>
        /// 添加所有服务
        /// </summary>
        /// <param name="services">服务集合</param>
        /// <param name="configuration">配置</param>
        /// <returns>服务集合</returns>
        public static IServiceCollection AddAllServices(this IServiceCollection services, IConfiguration configuration)
        {
            services.AddDatabaseServices(configuration)
                    .AddRepositoryServices()
                    .AddLoggingServices(configuration)
                    .AddSwaggerServices()
                    .AddCorsServices()
                    .AddCacheServices()
                    .AddAutoMapperServices()
                    .AddJwtAuthenticationServices(configuration)
                    .AddBusinessServices();

            return services;
        }
    }
}
